﻿//***********************************************************************
// Assembly         : IGolovkine.AoA.Core
// Author           : Ilia
// Created          : 06-11-2011
//
// Last Modified By : Ilia
// Last Modified On : 06-11-2011
// Description      : 
//
// Copyright        : (c) Microsoft. All rights reserved.
//***********************************************************************
using System;
using System.Linq;
using System.Reactive.Subjects;
using System.Reactive.Linq;

namespace IGolovkine.AoA.Tcp
{
    public class TcpTunnel //: ITunnel SOMETHING THAT TAKES A CHANNEL
    {
        private readonly Subject<TcpTunnelRoute> _routes;

        /// <summary>
        /// Initializes a new instance of the <see cref="TcpTunnel"/> class.
        /// </summary>
        /// <param name="channel">The channel.</param>
        public TcpTunnel(IMessageChannel channel)
        {
            _routes = new Subject<TcpTunnelRoute>();

            channel.Output
                .OfType<TcpConnectionInitiated>()
                .Select(message => new TcpOutboundTunnel(channel, new TcpConnection(message.Host, message.Port), message.ConnectionId))
                .Subscribe();

            channel.Output
                .OfType<AcceptTcpConnections>()
                .Select(message => new TcpInboundTunnel(channel, message.SourcePort, message.DestinationHost, message.DestinationPort))
                .Subscribe();

            _routes.Where(r => r.Direction == TcpTunnelDirection.Inbound)
                .Select(r => new AcceptTcpConnections(r.SourcePort, r.DestinationHost, r.DestinationPort))
                .Do(a => channel.Input.OnNext(a))
                .Subscribe();

            _routes.Where(r => r.Direction == TcpTunnelDirection.Outbound)
                .Select(r => new TcpInboundTunnel(channel, r.SourcePort, r.DestinationHost, r.DestinationPort))
                .Subscribe();
        }

        /// <summary>
        /// Gets the routes.
        /// </summary>
        public IObserver<TcpTunnelRoute> Routes
        {
            get { return _routes; }
        }
    }
}
